/**
  ******************************************************************************
  * @file    controller_protocol.c
  ******************************************************************************
  */

#include "controller_can.h"

#include "controller_fifo.h"
#include "controller_state.h"
#include "controller_protocol.h"

//#define CONTROLLER_DEBUG

#if defined(CONTROLLER_DEBUG)
#define CONTROLLER_TRACE(...)      \
    do                             \
    {                              \
        con_printf("\033[1;36m");  \
        con_printf(__VA_ARGS__);   \
        con_printf("\033[0m\r\n"); \
    } while (0)
#else
#define CONTROLLER_TRACE(...)
#endif

#define TCU_CAN_ADDRESS 0x8A   /* 上位机地址 */
#define MCU_CAN_ADDRESS 0xF6   /* 充电控制器地址 */

#define CAN_MAX_LEN     CAN_MAX_DLEN
#define CAN_FRAME_TYPE  CAN_EFF_ID_BITS

#define CON_MAX_BUFFER  2048

char *con_name = "can0";
uint32_t  con_bitrate = 125000;

/* 环形缓冲区 */
struct __fifo controller_fifo;

/* 序列号，范围 [1-255] */
static uint8_t heartbeatSequenceNumber;

/* 控制器实例指针 */
static void *s_controller_handle = NULL;

/* 环形缓冲区 - 用于CAN数据接收 */
static uint8_t controller_fifo_buffer[CON_MAX_BUFFER];

/* 日志回调函数, CAN的日志会从这里输出 */
/*
static int32_t user_state_logcb(char *message)
{
    CONTROLLER_TRACE("%s", message);
    return 0;
} */

/**
 * @brief Controller事件回调函数, 当CAN读取到报文时被触发
 *---
 * @param [in] handle: @n 实例句柄.
 * @param [in] frame_data: @n 帧数据.
 * @return None.
 * @see None.
 * @note None.
 */
static void con_recv_handler(void *handle, const struct can_frame *frame_data)
{
    (void)handle;

    fifo_in(&controller_fifo, (uint8_t *)&(frame_data->can_id), sizeof(uint32_t));
    uint8_t cnt;
    for(cnt = 0; cnt < CAN_MAX_LEN; cnt++)
    {
        fifo_in(&controller_fifo, &frame_data->data[cnt], sizeof(uint8_t));
    }
}

static int32_t send_frame_start_charg(con_start_charg_t *data)
{
    int32_t _res = 0;
    struct can_frame frame = {0};

    memset(&frame.data, 0xFF, sizeof(frame.data));

    size_t cnt;
    for(cnt = 0; cnt < sizeof(con_start_charg_t); cnt++)
    {
        frame.data[cnt] = (*((uint8_t *)data + cnt));
    }

    frame.can_dlc = CAN_MAX_LEN;

    frame.can_id |= CON_PRIORITY_START_CHARG << 26;
    frame.can_id |= CON_PDUFORMAT_START_CHARG << 16;
    frame.can_id |= MCU_CAN_ADDRESS << 8;
    frame.can_id |= TCU_CAN_ADDRESS;

    if(CAN_FRAME_TYPE == CAN_EFF_ID_BITS)
    {
        frame.can_id &= CAN_EFF_MASK; /* extended frame format (EFF) */
        frame.can_id |= CAN_EFF_FLAG;
    }
    else
    {
        frame.can_id &= CAN_SFF_MASK; /* standard frame format (SFF) */
    }

    controller_send(s_controller_handle, &frame);

    return _res;
}

static int32_t send_frame_stop_charg(con_stop_charg_t *data)
{
    int32_t _res = 0;
    struct can_frame frame = {0};

    memset(&frame.data, 0xFF, sizeof(frame.data));

    size_t cnt;
    for(cnt = 0; cnt < sizeof(con_stop_charg_t); cnt++)
    {
        frame.data[cnt] = (*((uint8_t *)data + cnt));
    }

    frame.can_dlc = CAN_MAX_LEN;

    frame.can_id |= CON_PRIORITY_STOP_CHARG << 26;
    frame.can_id |= CON_PDUFORMAT_STOP_CHARG << 16;
    frame.can_id |= MCU_CAN_ADDRESS << 8;
    frame.can_id |= TCU_CAN_ADDRESS;

    if(CAN_FRAME_TYPE == CAN_EFF_ID_BITS)
    {
        frame.can_id &= CAN_EFF_MASK; /* extended frame format (EFF) */
        frame.can_id |= CAN_EFF_FLAG;
    }
    else
    {
        frame.can_id &= CAN_SFF_MASK; /* standard frame format (SFF) */
    }

    controller_send(s_controller_handle, &frame);

    return _res;
}

static int32_t send_frame_time_sync(con_time_sync_t *data)
{
    int32_t _res = 0;
    struct can_frame frame = {0};

    memset(&frame.data, 0xFF, sizeof(frame.data));

    size_t cnt;
    for(cnt = 0; cnt < sizeof(con_time_sync_t); cnt++)
    {
        frame.data[cnt] = (*((uint8_t *)data + cnt));
    }

    frame.can_dlc = CAN_MAX_LEN;

    frame.can_id |= CON_PRIORITY_TIME_SYNC << 26;
    frame.can_id |= CON_PDUFORMAT_TIME_SYNC << 16;
    frame.can_id |= MCU_CAN_ADDRESS << 8;
    frame.can_id |= TCU_CAN_ADDRESS;

    if(CAN_FRAME_TYPE == CAN_EFF_ID_BITS)
    {
        frame.can_id &= CAN_EFF_MASK; /* extended frame format (EFF) */
        frame.can_id |= CAN_EFF_FLAG;
    }
    else
    {
        frame.can_id &= CAN_SFF_MASK; /* standard frame format (SFF) */
    }

    controller_send(s_controller_handle, &frame);

    return _res;
}

static int32_t send_frame_version_check(con_version_check_t *data)
{
    int32_t _res = 0;
    struct can_frame frame = {0};

    memset(&frame.data, 0xFF, sizeof(frame.data));

    size_t cnt;
    for(cnt = 0; cnt < sizeof(con_version_check_t); cnt++)
    {
        frame.data[cnt] = (*((uint8_t *)data + cnt));
    }

    frame.can_dlc = CAN_MAX_LEN;

    frame.can_id |= CON_PRIORITY_VERSION_CHECK << 26;
    frame.can_id |= CON_PDUFORMAT_VERSION_CHECK << 16;
    frame.can_id |= MCU_CAN_ADDRESS << 8;
    frame.can_id |= TCU_CAN_ADDRESS;

    if(CAN_FRAME_TYPE == CAN_EFF_ID_BITS)
    {
        frame.can_id &= CAN_EFF_MASK; /* extended frame format (EFF) */
        frame.can_id |= CAN_EFF_FLAG;
    }
    else
    {
        frame.can_id &= CAN_SFF_MASK; /* standard frame format (SFF) */
    }

    controller_send(s_controller_handle, &frame);

    return _res;
}

static int32_t send_frame_startup_force(con_startup_force_t *data)
{
    int32_t _res = 0;
    struct can_frame frame = {0};

    memset(&frame.data, 0xFF, sizeof(frame.data));

    size_t cnt;
    for(cnt = 0; cnt < sizeof(con_startup_force_t); cnt++)
    {
        frame.data[cnt] = (*((uint8_t *)data + cnt));
    }

    frame.can_dlc = CAN_MAX_LEN;

    frame.can_id |= CON_PRIORITY_STARTUP_FORCE << 26;
    frame.can_id |= CON_PDUFORMAT_STARTUP_FORCE << 16;
    frame.can_id |= MCU_CAN_ADDRESS << 8;
    frame.can_id |= TCU_CAN_ADDRESS;

    if(CAN_FRAME_TYPE == CAN_EFF_ID_BITS)
    {
        frame.can_id &= CAN_EFF_MASK; /* extended frame format (EFF) */
        frame.can_id |= CAN_EFF_FLAG;
    }
    else
    {
        frame.can_id &= CAN_SFF_MASK; /* standard frame format (SFF) */
    }

    controller_send(s_controller_handle, &frame);

    return _res;
}

static int32_t send_frame_lock_ctrl(con_lock_ctrl_t *data)
{
    int32_t _res = 0;
    struct can_frame frame = {0};

    memset(&frame.data, 0xFF, sizeof(frame.data));

    size_t cnt;
    for(cnt = 0; cnt < sizeof(con_lock_ctrl_t); cnt++)
    {
        frame.data[cnt] = (*((uint8_t *)data + cnt));
    }

    frame.can_dlc = CAN_MAX_LEN;

    frame.can_id |= CON_PRIORITY_LOCK_CTRL << 26;
    frame.can_id |= CON_PDUFORMAT_LOCK_CTRL << 16;
    frame.can_id |= MCU_CAN_ADDRESS << 8;
    frame.can_id |= TCU_CAN_ADDRESS;

    if(CAN_FRAME_TYPE == CAN_EFF_ID_BITS)
    {
        frame.can_id &= CAN_EFF_MASK; /* extended frame format (EFF) */
        frame.can_id |= CAN_EFF_FLAG;
    }
    else
    {
        frame.can_id &= CAN_SFF_MASK; /* standard frame format (SFF) */
    }

    controller_send(s_controller_handle, &frame);

    return _res;
}

static int32_t send_frame_power_ctrl(con_power_ctrl_t *data)
{
    int32_t _res = 0;
    struct can_frame frame = {0};

    memset(&frame.data, 0xFF, sizeof(frame.data));

    size_t cnt;
    for(cnt = 0; cnt < sizeof(con_power_ctrl_t); cnt++)
    {
        frame.data[cnt] = (*((uint8_t *)data + cnt));
    }

    frame.can_dlc = CAN_MAX_LEN;

    frame.can_id |= CON_PRIORITY_POWER_CTRL << 26;
    frame.can_id |= CON_PDUFORMAT_POWER_CTRL << 16;
    frame.can_id |= MCU_CAN_ADDRESS << 8;
    frame.can_id |= TCU_CAN_ADDRESS;

    if(CAN_FRAME_TYPE == CAN_EFF_ID_BITS)
    {
        frame.can_id &= CAN_EFF_MASK; /* extended frame format (EFF) */
        frame.can_id |= CAN_EFF_FLAG;
    }
    else
    {
        frame.can_id &= CAN_SFF_MASK; /* standard frame format (SFF) */
    }

    controller_send(s_controller_handle, &frame);

    return _res;
}

static int32_t send_frame_sys_set(con_sys_get_set_t *data)
{
    int32_t _res = 0;
    struct can_frame frame = {0};

    memset(&frame.data, 0xFF, sizeof(frame.data));
    frame.data[0] = 0x01;
    frame.data[1] = data->gnu_no;
    frame.data[2] = sizeof(con_sys_get_set_t);
    frame.data[3] = 0x05;
    frame.data[4] = data->gnu_no;
    frame.data[5] = data->set_type;
    frame.data[6] = data->lock_type;
    frame.data[7] = data->temp_type;

    frame.can_dlc = CAN_MAX_LEN;

    frame.can_id |= CON_PRIORITY_SYS_SET << 26;
    frame.can_id |= CON_PDUFORMAT_SYS_GET_SET << 16;
    frame.can_id |= MCU_CAN_ADDRESS << 8;
    frame.can_id |= TCU_CAN_ADDRESS;

    if(CAN_FRAME_TYPE == CAN_EFF_ID_BITS)
    {
        frame.can_id &= CAN_EFF_MASK; /* extended frame format (EFF) */
        frame.can_id |= CAN_EFF_FLAG;
    }
    else
    {
        frame.can_id &= CAN_SFF_MASK; /* standard frame format (SFF) */
    }

    controller_send(s_controller_handle, &frame);

    memset(&frame.data, 0xFF, sizeof(frame.data));
    frame.data[0] = 0x02;
    frame.data[1] = data->gnu_no;
    frame.data[2] = data->meter_baud;
    frame.data[3] = data->insulation;
    frame.data[4] = data->bleed;
    frame.data[5] = data->fan;
    frame.data[6] = data->travel_switch;
    frame.data[7] = data->model_type;

    controller_send(s_controller_handle, &frame);

    memset(&frame.data, 0xFF, sizeof(frame.data));
    frame.data[0] = 0x03;
    frame.data[1] = data->gnu_no;
    frame.data[2] = data->lock_fb;
    frame.data[3] = data->in_feedback;
    frame.data[4] = data->temp_ctrl;
    frame.data[5] = data->out_sampling;
    frame.data[6] = data->meter_kw;
    frame.data[7] = data->ct;

    controller_send(s_controller_handle, &frame);

    memset(&frame.data, 0xFF, sizeof(frame.data));
    frame.data[0] = 0x04;
    frame.data[1] = data->gnu_no;
    frame.data[2] = data->gnu_type;
    frame.data[3] = (uint8_t)((data->model_vol_max >> 0) & 0xFF);
    frame.data[4] = (uint8_t)((data->model_vol_max >> 8) & 0xFF);
    frame.data[5] = (uint8_t)((data->model_vol_min >> 0) & 0xFF);
    frame.data[6] = (uint8_t)((data->model_vol_min >> 8) & 0xFF);
    frame.data[7] = (uint8_t)((data->model_cur_max >> 0) & 0xFF);

    controller_send(s_controller_handle, &frame);

    memset(&frame.data, 0xFF, sizeof(frame.data));
    frame.data[0] = 0x05;
    frame.data[1] = data->gnu_no;
    frame.data[2] = (uint8_t)((data->model_cur_max >> 8) & 0xFF);
    frame.data[3] = (uint8_t)((data->model_cur_min >> 0) & 0xFF);
    frame.data[4] = (uint8_t)((data->model_cur_min >> 8) & 0xFF);
    frame.data[5] = data->gunno_a_model_num;
    frame.data[6] = data->gunno_b_model_num;

    controller_send(s_controller_handle, &frame);

    return _res;
}

static int32_t send_frame_carinfo(con_carinfo_t *data)
{
    int32_t _res = 0;
    struct can_frame frame = {0};

    memset(&frame.data, 0xFF, sizeof(frame.data));

    size_t cnt;
    for(cnt = 0; cnt < sizeof(con_carinfo_t); cnt++)
    {
        frame.data[cnt] = (*((uint8_t *)data + cnt));
    }

    frame.can_dlc = CAN_MAX_LEN;

    frame.can_id |= CON_PRIORITY_CARINFO << 26;
    frame.can_id |= CON_PDUFORMAT_CARINFO << 16;
    frame.can_id |= MCU_CAN_ADDRESS << 8;
    frame.can_id |= TCU_CAN_ADDRESS;

    if(CAN_FRAME_TYPE == CAN_EFF_ID_BITS)
    {
        frame.can_id &= CAN_EFF_MASK; /* extended frame format (EFF) */
        frame.can_id |= CAN_EFF_FLAG;
    }
    else
    {
        frame.can_id &= CAN_SFF_MASK; /* standard frame format (SFF) */
    }

    controller_send(s_controller_handle, &frame);

    return _res;
}

static int32_t send_frame_start_update(con_start_update_t *data)
{
    int32_t _res = 0;
    struct can_frame frame = {0};

    memset(&frame.data, 0xFF, sizeof(frame.data));

    size_t cnt;
    for(cnt = 0; cnt < sizeof(con_start_update_t); cnt++)
    {
        frame.data[cnt] = (*((uint8_t *)data + cnt));
    }

    frame.can_dlc = CAN_MAX_LEN;

    frame.can_id |= CON_PRIORITY_START_UPDATED << 26;
    frame.can_id |= CON_PDUFORMAT_START_UPDATE << 16;
    frame.can_id |= MCU_CAN_ADDRESS << 8;
    frame.can_id |= TCU_CAN_ADDRESS;

    if(CAN_FRAME_TYPE == CAN_EFF_ID_BITS)
    {
        frame.can_id &= CAN_EFF_MASK; /* extended frame format (EFF) */
        frame.can_id |= CAN_EFF_FLAG;
    }
    else
    {
        frame.can_id &= CAN_SFF_MASK; /* standard frame format (SFF) */
    }

    controller_send(s_controller_handle, &frame);

    return _res;
}

static int32_t send_frame_update_data(con_update_data_t *data)
{
    int32_t _res = 0;
    struct can_frame frame = {0};

    memset(&frame.data, 0xFF, sizeof(frame.data));

    size_t cnt;
    for(cnt = 0; cnt < sizeof(con_start_update_t); cnt++)
    {
        frame.data[cnt] = (*((uint8_t *)data + cnt));
    }

    frame.can_dlc = CAN_MAX_LEN;

    frame.can_id |= CON_PRIORITY_UPDATED_DATA << 26;
    frame.can_id |= CON_PDUFORMAT_UPDATE_DATA << 16;
    frame.can_id |= MCU_CAN_ADDRESS << 8;
    frame.can_id |= TCU_CAN_ADDRESS;

    if(CAN_FRAME_TYPE == CAN_EFF_ID_BITS)
    {
        frame.can_id &= CAN_EFF_MASK; /* extended frame format (EFF) */
        frame.can_id |= CAN_EFF_FLAG;
    }
    else
    {
        frame.can_id &= CAN_SFF_MASK; /* standard frame format (SFF) */
    }

    controller_send(s_controller_handle, &frame);

    return _res;
}

static int32_t send_frame_sys_check(con_system_check_t *data)
{
    int32_t _res = 0;
    struct can_frame frame = {0};

    memset(&frame.data, 0xFF, sizeof(frame.data));

    size_t cnt;
    for(cnt = 0; cnt < sizeof(con_start_update_t); cnt++)
    {
        frame.data[cnt] = (*((uint8_t *)data + cnt));
    }

    frame.can_dlc = CAN_MAX_LEN;

    frame.can_id |= CON_PRIORITY_SYS_CHECK << 26;
    frame.can_id |= CON_PDUFORMAT_SYS_CHECK << 16;
    frame.can_id |= MCU_CAN_ADDRESS << 8;
    frame.can_id |= TCU_CAN_ADDRESS;

    if(CAN_FRAME_TYPE == CAN_EFF_ID_BITS)
    {
        frame.can_id &= CAN_EFF_MASK; /* extended frame format (EFF) */
        frame.can_id |= CAN_EFF_FLAG;
    }
    else
    {
        frame.can_id &= CAN_SFF_MASK; /* standard frame format (SFF) */
    }

    controller_send(s_controller_handle, &frame);

    return _res;
}

static int32_t send_frame_feedback_charg_start_result(con_feedback_charg_start_result_t *data)
{
    int32_t _res = 0;
    struct can_frame frame = {0};

    memset(&frame.data, 0xFF, sizeof(frame.data));

    size_t cnt;
    for(cnt = 0; cnt < sizeof(con_feedback_charg_start_result_t); cnt++)
    {
        frame.data[cnt] = (*((uint8_t *)data + cnt));
    }

    frame.can_dlc = CAN_MAX_LEN;

    frame.can_id |= CON_PRIORITY_FEEDBACK_CHARG_START_RESULT << 26;
    frame.can_id |= CON_PDUFORMAT_FEEDBACK_CHARG_START_RESULT << 16;
    frame.can_id |= MCU_CAN_ADDRESS << 8;
    frame.can_id |= TCU_CAN_ADDRESS;

    if(CAN_FRAME_TYPE == CAN_EFF_ID_BITS)
    {
        frame.can_id &= CAN_EFF_MASK; /* extended frame format (EFF) */
        frame.can_id |= CAN_EFF_FLAG;
    }
    else
    {
        frame.can_id &= CAN_SFF_MASK; /* standard frame format (SFF) */
    }

    controller_send(s_controller_handle, &frame);

    return _res;
}

static int32_t send_frame_feedback_charg_stop_result(con_feedback_charg_stop_result_t *data)
{
    int32_t _res = 0;
    struct can_frame frame = {0};

    memset(&frame.data, 0xFF, sizeof(frame.data));

    size_t cnt;
    for(cnt = 0; cnt < sizeof(con_feedback_charg_stop_result_t); cnt++)
    {
        frame.data[cnt] = (*((uint8_t *)data + cnt));
    }

    frame.can_dlc = CAN_MAX_LEN;

    frame.can_id |= CON_PRIORITY_FEEDBACK_CHARG_STOP_RESULT << 26;
    frame.can_id |= CON_PDUFORMAT_FEEDBACK_CHARG_STOP_RESULT << 16;
    frame.can_id |= MCU_CAN_ADDRESS << 8;
    frame.can_id |= TCU_CAN_ADDRESS;

    if(CAN_FRAME_TYPE == CAN_EFF_ID_BITS)
    {
        frame.can_id &= CAN_EFF_MASK; /* extended frame format (EFF) */
        frame.can_id |= CAN_EFF_FLAG;
    }
    else
    {
        frame.can_id &= CAN_SFF_MASK; /* standard frame format (SFF) */
    }

    controller_send(s_controller_handle, &frame);

    return _res;
}

static int32_t send_frame_feedback_telemetry(con_feedback_telemetry_t *data)
{
    int32_t _res = 0;
    struct can_frame frame = {0};

    memset(&frame.data, 0xFF, sizeof(frame.data));

    size_t cnt;
    for(cnt = 0; cnt < sizeof(con_feedback_telemetry_t); cnt++)
    {
        frame.data[cnt] = (*((uint8_t *)data + cnt));
    }

    frame.can_dlc = CAN_MAX_LEN;

    frame.can_id |= CON_PRIORITY_FEEDBACK_TELEMETRY << 26;
    frame.can_id |= CON_PDUFORMAT_FEEDBACK_TELEMETRY << 16;
    frame.can_id |= MCU_CAN_ADDRESS << 8;
    frame.can_id |= TCU_CAN_ADDRESS;

    if(CAN_FRAME_TYPE == CAN_EFF_ID_BITS)
    {
        frame.can_id &= CAN_EFF_MASK; /* extended frame format (EFF) */
        frame.can_id |= CAN_EFF_FLAG;
    }
    else
    {
        frame.can_id &= CAN_SFF_MASK; /* standard frame format (SFF) */
    }

    controller_send(s_controller_handle, &frame);

    return _res;
}

static int32_t send_frame_feedback_telecommand(con_feedback_telecommand_t *data)
{
    int32_t _res = 0;
    struct can_frame frame = {0};

    memset(&frame.data, 0xFF, sizeof(frame.data));

    size_t cnt;
    for(cnt = 0; cnt < sizeof(con_feedback_telecommand_t); cnt++)
    {
        frame.data[cnt] = (*((uint8_t *)data + cnt));
    }

    frame.can_dlc = CAN_MAX_LEN;

    frame.can_id |= CON_PRIORITY_FEEDBACK_TELECOMMAND << 26;
    frame.can_id |= CON_PDUFORMAT_FEEDBACK_TELECOMMAND << 16;
    frame.can_id |= MCU_CAN_ADDRESS << 8;
    frame.can_id |= TCU_CAN_ADDRESS;

    if(CAN_FRAME_TYPE == CAN_EFF_ID_BITS)
    {
        frame.can_id &= CAN_EFF_MASK; /* extended frame format (EFF) */
        frame.can_id |= CAN_EFF_FLAG;
    }
    else
    {
        frame.can_id &= CAN_SFF_MASK; /* standard frame format (SFF) */
    }

    controller_send(s_controller_handle, &frame);

    return _res;
}

static int32_t send_frame_heartbeat(con_heartbeat_t *data)
{
    int32_t _res = 0;
    struct can_frame frame = {0};

    memset(&frame.data, 0xFF, sizeof(frame.data));

    if(0 == heartbeatSequenceNumber)
    {
        heartbeatSequenceNumber = 1;
    }
    data->sequence_number = heartbeatSequenceNumber++;

    size_t cnt;
    for(cnt = 0; cnt < sizeof(con_heartbeat_t); cnt++)
    {
        frame.data[cnt] = (*((uint8_t *)data + cnt));
    }

    frame.can_dlc = CAN_MAX_LEN;

    frame.can_id |= CON_PRIORITY_HEARTBEAT << 26;
    frame.can_id |= CON_PDUFORMAT_HEARTBEAT << 16;
    frame.can_id |= MCU_CAN_ADDRESS << 8;
    frame.can_id |= TCU_CAN_ADDRESS;

    if(CAN_FRAME_TYPE == CAN_EFF_ID_BITS)
    {
        frame.can_id &= CAN_EFF_MASK; /* extended frame format (EFF) */
        frame.can_id |= CAN_EFF_FLAG;
    }
    else
    {
        frame.can_id &= CAN_SFF_MASK; /* standard frame format (SFF) */
    }

    controller_send(s_controller_handle, &frame);

    return _res;
}

static int32_t send_frame_tcu_error(con_tcu_error_t *data)
{
    int32_t _res = 0;
    struct can_frame frame = {0};

    memset(&frame.data, 0xFF, sizeof(frame.data));

    size_t cnt;
    for(cnt = 0; cnt < sizeof(con_tcu_error_t); cnt++)
    {
        frame.data[cnt] = (*((uint8_t *)data + cnt));
    }

    frame.can_dlc = CAN_MAX_LEN;

    frame.can_id |= CON_PRIORITY_TCU_ERROR << 26;
    frame.can_id |= CON_PDUFORMAT_TCU_ERROR << 16;
    frame.can_id |= MCU_CAN_ADDRESS << 8;
    frame.can_id |= TCU_CAN_ADDRESS;

    if(CAN_FRAME_TYPE == CAN_EFF_ID_BITS)
    {
        frame.can_id &= CAN_EFF_MASK; /* extended frame format (EFF) */
        frame.can_id |= CAN_EFF_FLAG;
    }
    else
    {
        frame.can_id &= CAN_SFF_MASK; /* standard frame format (SFF) */
    }

    controller_send(s_controller_handle, &frame);

    return _res;
}

int32_t con_linkkit_new(void)
{
    /* 配置CAN的日志输出 */
    /*
    controller_state_set_logcb(user_state_logcb); */

    /* 创建1个CON实例并内部初始化默认参数 */
    s_controller_handle = controller_init();
    if (NULL == s_controller_handle)
    {
        return -1;
    }

    /* 配置CAN接口 */
    controller_setopt(s_controller_handle, CONTROLLER_OPTION_NAME, (void *)con_name);
    /* 配置数据到达时, CON应调用的用户回调函数 */
    controller_setopt(s_controller_handle, CONTROLLER_OPTION_RECV_HANDLER, con_recv_handler);

    /* 建立连接 */
    int32_t res = 0;
    res = controller_connect(s_controller_handle, con_bitrate);
    if(res < 0)
    {
        controller_deinit(s_controller_handle);
        return res;
    }

    /* 初始化环形缓冲区 */
    fifo_init(&controller_fifo, controller_fifo_buffer, CON_MAX_BUFFER);

    return 0;
}

int32_t con_linkkit_free(void)
{
    if (NULL == s_controller_handle)
    {
        return -1;
    }

    controller_disconnect(s_controller_handle);
    controller_deinit(s_controller_handle);

    return 0;
}

int32_t con_linkkit_reset(void)
{
    if (NULL == s_controller_handle)
    {
        return -1;
    }

    controller_disconnect(s_controller_handle);
    controller_connect(s_controller_handle, con_bitrate);

    return 0;
}

int32_t con_yield(void)
{
    return controller_recv(s_controller_handle);
}

void con_send_data(con_pduformat_enum frame_type, void *param)
{
    switch(frame_type)
    {
        case CON_PDUFORMAT_START_CHARG:
            send_frame_start_charg((con_start_charg_t *)param);
            break;
        case CON_PDUFORMAT_STOP_CHARG:
            send_frame_stop_charg((con_stop_charg_t *)param);
            break;
        case CON_PDUFORMAT_TIME_SYNC:
            send_frame_time_sync((con_time_sync_t *)param);
            break;
        case CON_PDUFORMAT_VERSION_CHECK:
            send_frame_version_check((con_version_check_t *)param);
            break;
        case CON_PDUFORMAT_STARTUP_FORCE:
            send_frame_startup_force((con_startup_force_t *)param);
            break;
        case CON_PDUFORMAT_LOCK_CTRL:
            send_frame_lock_ctrl((con_lock_ctrl_t *)param);
            break;
        case CON_PDUFORMAT_POWER_CTRL:
            send_frame_power_ctrl((con_power_ctrl_t *)param);
            break;
        case CON_PDUFORMAT_SYS_GET_SET:
            send_frame_sys_set((con_sys_get_set_t *)param);
            break;
        case CON_PDUFORMAT_CARINFO:
            send_frame_carinfo((con_carinfo_t *)param);
            break;
        case CON_PDUFORMAT_START_UPDATE:
            send_frame_start_update((con_start_update_t *)param);
            break;
        case CON_PDUFORMAT_UPDATE_DATA:
            send_frame_update_data((con_update_data_t *)param);
            break;
        case CON_PDUFORMAT_FEEDBACK_UPDATE_RESULT:
            break;
        case CON_PDUFORMAT_SYS_CHECK:
            send_frame_sys_check((con_system_check_t *)param);
            break;
        case CON_PDUFORMAT_FEEDBACK_CHARG_START_RESULT:
            send_frame_feedback_charg_start_result((con_feedback_charg_start_result_t *)param);
            break;
        case CON_PDUFORMAT_FEEDBACK_CHARG_STOP_RESULT:
            send_frame_feedback_charg_stop_result((con_feedback_charg_stop_result_t *)param);
            break;
        case CON_PDUFORMAT_FEEDBACK_TELEMETRY:
            send_frame_feedback_telemetry((con_feedback_telemetry_t *)param);
            break;
        case CON_PDUFORMAT_FEEDBACK_TELECOMMAND:
            send_frame_feedback_telecommand((con_feedback_telecommand_t *)param);
            break;
        case CON_PDUFORMAT_FEEDBACK_WLINE_TELECOMMAND:
            break;
        case CON_PDUFORMAT_HEARTBEAT:
            send_frame_heartbeat((con_heartbeat_t *)param);
            break;
        case CON_PDUFORMAT_TCU_ERROR:
            send_frame_tcu_error((con_tcu_error_t *)param);
            break;
        default:
            break;
    }
}
